package com.bsj.power.pls.mqtt.listener;

import com.bsj.power.common.netty.*;
import com.bsj.power.common.util.StringUtils;
import com.bsj.power.pls.handle.CTDataQueue;
import com.bsj.power.pls.netty.CTInstructUtils;
import com.bsj.power.pls.netty.CachedChannelMap;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.iot.mqtt.codec.MqttPublishMessage;
import net.dreamlu.iot.mqtt.codec.MqttQoS;
import net.dreamlu.iot.mqtt.core.server.event.IMqttMessageListener;
import net.dreamlu.iot.mqtt.spring.server.MqttServerTemplate;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.tio.core.ChannelContext;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * @author yinhao
 * @version 1.0
 * @description 客户端消息监听
 * @date 2023/11/7
 */
@Slf4j
public class MqttServerMessageListener implements IMqttMessageListener, SmartInitializingSingleton {

    @Autowired
    private ApplicationContext applicationContext;

    private MqttServerTemplate mqttServer;

    @Override
    public void onMessage(ChannelContext context, String clientId, String topic, MqttQoS qoS, MqttPublishMessage message) {
        String msg = new String(message.getPayload(), StandardCharsets.UTF_8);
        msg = msg.replaceAll("\n", "").replaceAll("\r", "").replaceAll(" ", "");
        log.info("clientId: {} topic: {} msg: {}", clientId, topic, msg);

        // 去掉头，去掉尾，取中间
        if (msg.length() < 3) {
            log.info("错误的数据和长度，数据={}， 长度={}", msg, msg.length());
            return;
        }
        String substring = msg.substring(1, msg.length() - 1);
        String[] split = substring.split(",");
        String flag = split[0];

        CTData ctData = null;

        byte[] reply;

        switch (flag) {
            case CT60_constant.CN:
                CTLoginData CTLoginData = analysisCTLoginData(msg, split);
                if (CTLoginData == null) {
                    break;
                }
                log.info("接收到设备登入报文，设备号是：{}", CTLoginData.getDeviceId());

                // 回复
                reply = CTInstructUtils.assembleLoginReply(CTLoginData.getDeviceId());

                mqttServer.publish(clientId, CTInstructUtils.getTopicSend(CTLoginData.getDeviceId()), reply);

                ctData = CTLoginData;

                break;
            case CT60_constant.CH:
                CTKeepAliveData CTKeepAliveData = analysisCTKeepAliveData(msg, split);
                if (CTKeepAliveData == null) {
                    break;
                }

                ctData = CTKeepAliveData;

                break;
            case CT60_constant.AC: // AC和CQ命令解析一样
            case CT60_constant.CQ:
                ACDeviceStatusData acDeviceStatusData = analysisACDeviceStatusData(msg, split);
                if (acDeviceStatusData == null) {
                    break;
                }

                ctData = acDeviceStatusData;

                break;
            case CT60_constant.CP:
                CPPopData cpPopData = analysisCPPopData(msg, split);
                if (cpPopData == null) {
                    break;
                }
                ctData = cpPopData;

                break;
            case CT60_constant.CR:
                CRReceiveData crReceiveData = analysisCRReceiveData(msg, split);
                if (crReceiveData == null) {
                    break;
                }

                // 回复
                reply = CTInstructUtils.assembleStockReturnReply(crReceiveData.getDeviceId(), crReceiveData.getSerialNum(), 1);

                mqttServer.publish(clientId, CTInstructUtils.getTopicSend(crReceiveData.getDeviceId()), reply);

                ctData = crReceiveData;
                break;
            case CT60_constant.CL:
                CLStockControlData clStockControlData = analysis_CL(msg, split);
                if (clStockControlData == null) {
                    break;
                }

                ctData = clStockControlData;
                break;
            case CT60_constant.OT:

                break;
            case CT60_constant.SQ:
                SQStockInfoData sqStockInfoData = analysis_SQ(msg, split, clientId);

                break;
            default:
                break;

        }

        // 消息发送到Queue处理
        if (ctData != null) {
            try {
                CTDataQueue.push(ctData);
                pushChannel(clientId, ctData.getDeviceId());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }


    }

    private SQStockInfoData analysis_SQ(String msg, String[] split, String clientId) {
        // todo 不处理了直接查查询日志看
        log.info("收到仓位子板信息查询回复clientId={}原始消息是={}", clientId, msg);

        return null;
    }

    private CTLoginData analysisCTLoginData(String msg, String[] arr) {
        if (arr.length != 8) {
            log.warn("CN数据长度不为8，不解析，原始数据是={}", msg);
            return null;
        }
        CTLoginData CTLoginData = new CTLoginData();
        for (int i = 0; i < arr.length; i++) {
            String s = arr[i];
            switch (i) {
                case 0:
                    CTLoginData.setDataType(CT60_constant.CN);
                    break;
                case 1:
                    CTLoginData.setDeviceId(s);
                    break;
                case 2:
                    CTLoginData.setProductKey(s);
                    break;
                case 3:
                    CTLoginData.setFirmwareVer(s);
                    break;
                case 4:
                    CTLoginData.setHardwareVer(s);
                    break;
                case 5:
                    CTLoginData.setNetworkMac(s);
                    break;
                case 6:
                    CTLoginData.setIp(s);
                    break;
                case 7:
                    CTLoginData.setCheckCode(s);
                    break;
            }
        }
        return CTLoginData;
    }

    private CTKeepAliveData analysisCTKeepAliveData(String msg, String[] arr) {
        if (arr.length != 4) {
            log.warn("CH数据长度不为4，不解析，原始数据是={}", msg);
            return null;
        }
        CTKeepAliveData CTKeepAliveData = new CTKeepAliveData();
        for (int i = 0; i < arr.length; i++) {
            String s = arr[i];
            if (i == 0) {
                CTKeepAliveData.setDataType(CT60_constant.CH);
            } else if (i == 1) {
                CTKeepAliveData.setMessageId(s);
            } else if (i == 2) {
                CTKeepAliveData.setDeviceId(s);
            } else if (i == 3) {
                CTKeepAliveData.setCheckCode(s);
            }
        }
        return CTKeepAliveData;
    }


    private ACDeviceStatusData analysisACDeviceStatusData(String msg, String[] arr) {
        if (arr.length != 6) {
            log.warn("AC数据长度不为6，不解析，原始数据是={}", msg);
            return null;
        }
        ACDeviceStatusData acDeviceStatusData = new ACDeviceStatusData();
        for (int i = 0; i < arr.length; i++) {
            String s = arr[i];
            switch (i) {
                case 0:
                    acDeviceStatusData.setDataType(CT60_constant.AC);
                    break;
                case 1:
                    acDeviceStatusData.setMessageId(s);
                    acDeviceStatusData.setReceiveTime(Long.parseLong(s));
                    break;
                case 2:
                    acDeviceStatusData.setDeviceId(s);
                    break;
                case 3:
                    acDeviceStatusData.setStockNumber(Integer.parseInt(s));
                    break;
                case 4:
                    String[] split = s.split(";"); // 以分号分出每一个仓位信息集

                    List<StockInfo> stockInfos = new ArrayList<>();
                    for (String s1 : split) {
                        String[] split1 = s1.split("\\*"); // 以*号分出每一个仓位的字符标识
                        StockInfo stockInfo = new StockInfo();
                        for (String s2 : split1) {
                            if (StringUtils.isEmpty(s2)) {
                                continue;
                            }
                            String[] split2 = s2.split(":");
                            String s3 = null;
                            String s4 = null;
                            if (split2.length == 1) { // 这里长度不是1就是2
                                s3 = split2[0];
                            } else {
                                s3 = split2[0];
                                s4 = split2[1];
                            }
                            switch (s3) {
                                case "S":
                                    if (s4 != null) {
                                        stockInfo.setSerialNum(Integer.parseInt(s4));
                                    } else {
                                        stockInfo.setSerialNum(null);
                                    }
                                    break;
                                case "T":
                                    if (s4 != null) {
                                        stockInfo.setState(Integer.parseInt(s4));
                                    } else {
                                        stockInfo.setState(null);
                                    }
                                    break;
                                case "N":
                                    stockInfo.setUwbNo(s4);
                                    break;
                                case "P":
                                    stockInfo.setUwbPower(s4);
                                    break;
                                case "V":
                                    stockInfo.setUwbVersion(s4);
                                    break;
                                default:
                                    break;
                            }
                        }
                        stockInfos.add(stockInfo);
                    }
                    acDeviceStatusData.setStockInfos(stockInfos);
                    break;
                case 5:
                    acDeviceStatusData.setCheckCode(s);
                    break;
            }
        }
        return acDeviceStatusData;
    }


    private CPPopData analysisCPPopData(String msg, String[] arr) {
        if (arr.length != 5) {
            log.warn("CP数据长度不为5，不解析，原始数据是={}", msg);
            return null;
        }
        CPPopData cpPopData = new CPPopData();
        for (int i = 0; i < arr.length; i++) {
            String s = arr[i];
            switch (i) {
                case 0:
                    cpPopData.setDataType(CT60_constant.CP);
                    break;
                case 1:
                    cpPopData.setMessageId(s);
                    cpPopData.setReceiveTime(System.currentTimeMillis() / 1000);
                    break;
                case 2:
                    cpPopData.setDeviceId(s);
                    break;
                case 3:
                    String[] split = s.split(";"); // 以分号分出每一个弹出结果信息

                    for (String s1 : split) {
                        String[] split1 = s1.split("\\*"); // 以*号分出每一个信息的字符标识
                        for (String s2 : split1) {
                            if (StringUtils.isEmpty(s2)) {
                                continue;
                            }
                            String[] split2 = s2.split(":");
                            String s3 = split2[0];
                            String s4 = split2[1];
                            switch (s3) {
                                case "R":
                                    cpPopData.setResult(Integer.parseInt(s4));
                                    break;
                                case "S":
                                    cpPopData.setSerialNum(Integer.parseInt(s4));
                                    break;
                                case "N":
                                    cpPopData.setUwbId(s4);
                                    break;
                                case "P":
                                    cpPopData.setUwbPower(s4);
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    break;
                case 4:
                    cpPopData.setCheckCode(s);
                    break;
            }
        }
        return cpPopData;
    }


    private CRReceiveData analysisCRReceiveData(String msg, String[] arr) {
        if (arr.length != 5) {
            log.warn("CR数据长度不为5，不解析，原始数据是={}", msg);
            return null;
        }
        CRReceiveData crReceiveData = new CRReceiveData();
        for (int i = 0; i < arr.length; i++) {
            String s = arr[i];
            switch (i) {
                case 0:
                    crReceiveData.setDataType(CT60_constant.CR);
                    break;
                case 1:
                    // 这个是设备上行的消息id，协议是时间戳，但是要区分设备是联网还是网口（内网），
                    // 联网的话是时间戳，网口（内网）是服务端最后一条消息的id
                    crReceiveData.setMessageId(s);
                    crReceiveData.setReceiveTime(System.currentTimeMillis() / 1000);
                    break;
                case 2:
                    crReceiveData.setDeviceId(s);
                    break;
                case 3:
                    String[] split = s.split(";"); // 以分号分出每一个归还结果信息

                    for (String s1 : split) {
                        String[] split1 = s1.split("\\*"); // 以*号分出每一个信息的字符标识
                        for (String s2 : split1) {
                            if (StringUtils.isEmpty(s2)) {
                                continue;
                            }
                            String[] split2 = s2.split(":");
                            String s3 = split2[0];
                            String s4 = split2[1];
                            switch (s3) {
                                case "R":
                                    crReceiveData.setResult(Integer.parseInt(s4));
                                    break;
                                case "S":
                                    crReceiveData.setSerialNum(Integer.parseInt(s4));
                                    break;
                                case "N":
                                    crReceiveData.setUwbId(s4);
                                    break;
                                case "P":
                                    crReceiveData.setUwbPower(s4);
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    break;
                case 4:
                    crReceiveData.setCheckCode(s);
                    break;
            }
        }
        return crReceiveData;
    }

    private CLStockControlData analysis_CL(String msg, String[] arr) {
        if (arr.length != 5) {
            log.warn("CL数据长度不为5，不解析，原始数据是={}", msg);
            return null;
        }
        CLStockControlData clStockControlData = new CLStockControlData();
        for (int i = 0; i < arr.length; i++) {
            String s = arr[i];
            switch (i) {
                case 0:
                    clStockControlData.setDataType(CT60_constant.CL);
                    break;
                case 1:
                    // 这个是设备上行的消息id，协议是时间戳，但是要区分设备是联网还是网口（内网），
                    // 联网的话是时间戳，网口（内网）是服务端最后一条消息的id
                    clStockControlData.setMessageId(s);
                    clStockControlData.setReceiveTime(System.currentTimeMillis() / 1000);
                    break;
                case 2:
                    clStockControlData.setDeviceId(s);
                    break;
                case 3:
                    String[] split = s.split(";"); // 以分号分出每一个归还结果信息

                    for (String s1 : split) {
                        String[] split1 = s1.split("\\*"); // 以*号分出每一个信息的字符标识
                        for (String s2 : split1) {
                            if (StringUtils.isEmpty(s2)) {
                                continue;
                            }
                            String[] split2 = s2.split(":");
                            String s3 = split2[0];
                            String s4 = split2[1];
                            switch (s3) {
                                case "S":
                                    clStockControlData.setSerialNum(Integer.parseInt(s4));
                                    break;
                                case "T":
                                    clStockControlData.setState(Integer.parseInt(s4));
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    break;
                case 4:
                    clStockControlData.setCheckCode(s);
                    break;
            }
        }
        return clStockControlData;

    }


    /**
     * 管道缓存数据
     *
     * @param clientId clientId
     * @param deviceId 设备编号
     *
     */
    public void pushChannel(String clientId, String deviceId) {
        log.info("绑卡机编号连接信息：clientId：{}，deviceId：{}", clientId, deviceId);
        CachedChannelMap.push(clientId, deviceId);
    }


    @Override
    public void afterSingletonsInstantiated() {
        mqttServer = applicationContext.getBean(MqttServerTemplate.class);
    }
}
